#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <stdint.h>
#include "list.h"

typedef struct _LINE_
{
    struct _LINE_* next;
    struct _LINE_* pre;
    void* data;
    uint32_t datalen;
}LINE_t;

typedef struct _BODY_
{
    LINE_t* _head;
    LINE_t* _tail;
    int _num;
    int _max_num;
    int _max_len;
    void (*_data_free)(void*);
}BODY_t;

static void _free_line_data(BODY_t* body, void* data)
{
    if(NULL == data)
        return;
    
    if(NULL != body->_data_free)
    {
            body->_data_free(data);
            return;
    }
    
    free(data);
}

static void _destruct(LIST_t** _list)
{
    if(NULL == _list) return;

    LIST_t* list = *_list;
    BODY_t* body = (BODY_t*)list->_body;
    list->clear(list);
    LINE_t* line = body->_head;
    if(NULL != list->_body)
    {
        free(list->_body);
        list->_body = NULL;
    }

    free(list);
    list = NULL;
}

static void _clear(LIST_t* list)
{
    BODY_t* body = (BODY_t*)list->_body;
    LINE_t* line = body->_head;
    while(line != NULL)
    {
        LINE_t* p = line->next;
        _free_line_data(body, line->data);
        free(line);
        line = p;
    }
    body->_head = NULL;
    body->_tail = NULL;
}

static int _push_back(LIST_t* list, void* data, int len)
{   
    BODY_t* body = (BODY_t*) list->_body;
    if(body->_num >= body->_max_num || len > body->_max_len)
        return -1;

    LINE_t* line = (LINE_t*) malloc(sizeof(LINE_t));
    if(NULL == line)
        return -2;

    memset(line, 0, sizeof(LINE_t));

    line->data = malloc(len);
    if(NULL == line->data)
    {
        free(line);
        return -2;
    }
    memset(line->data, 0, len);
    memcpy(line->data, data, len);
    line->datalen = len;

    body->_num ++;

    if(NULL == body->_head) // 这里认为初始化, 头尾都指向同个结构
    {
        body->_head = line;
        body->_tail = line;
        return 0;
    }

    line->pre = body->_tail;
    body->_tail->next = line;
    body->_tail = line;

    return 0;
}

static int _push_front(LIST_t* list, void* data, int len)
{   
    BODY_t* body = (BODY_t*) list->_body;
    if(body->_num + 1 >= body->_max_num || len > body->_max_len)
        return -1;

    LINE_t* line = (LINE_t*) malloc(sizeof(LINE_t));
    if(NULL == line)
        return -2;

    memset(line, 0, sizeof(LINE_t));

    line->data = malloc(len);
    if(NULL == line->data)
    {
        free(line);
        return -2;
    }
    memset(line->data, 0, len);
    memcpy(line->data, data, len);
    line->datalen = len;

    body->_num ++;

    if(NULL == body->_head) // 这里认为初始化, 头尾都指向同个结构
    {
        body->_head = line;
        body->_tail = line;
        return 0;
    }

    line->next = body->_head;
    body->_head->pre = line;
    body->_head = line;

    return 0;
}

static void* _front(LIST_t* list)
{
    BODY_t* body = (BODY_t*)list->_body;
    if(NULL == body)
        return NULL;
    
    return body->_head->data;
}

static void* _back(LIST_t* list)
{
    BODY_t* body = (BODY_t*)list->_body;
    if(NULL == body)
        return NULL;

    return body->_tail->data;    
}

// 轮询删除, 正常不建议使用 O(n), data 是链表中的指针
static void _erase(LIST_t* list, void* data)
{
    BODY_t* body = (BODY_t*)list->_body;
    LINE_t* line = body->_head;
    while(line)
    {
        if(line->data == data)
        {
            LINE_t* p = line;
            if(NULL != p->pre)
                p->pre->next = p->next;
        
            if(NULL != p->next)
                p->next->pre = p->pre;
            
            if(body->_head == p)
            {
                body->_head = p->next;
            }
            if(body->_tail == p)
            {
                body->_tail = p->pre;
            }
            body->_num--;

            _free_line_data(body, line->data);
            free(line);
            break;
        }
        line = line->next;
    }
}

static void _pop_front(LIST_t* list)
{
    BODY_t* body = (BODY_t*)list->_body;
    LINE_t* line = body->_head;
    if(NULL == line)
        return;

    body->_head = line->next;

    if(NULL != body->_head)
        body->_head->pre = NULL;

    if(line == body->_tail)
        body->_tail = NULL;
    
    _free_line_data(body, line->data);
    free(line);

    body->_num--;
}

static void _pop_back(LIST_t* list)
{
    BODY_t* body = (BODY_t*)list->_body;
    LINE_t* line = body->_tail;
    if(NULL == line)
        return;
    
    body->_tail = line->pre;

    if(NULL != body->_tail)
        body->_tail->next = NULL;

    if(line == body->_head)
        body->_head = NULL;

    _free_line_data(body, line->data);
    free(line);

    body->_num--;
}

static bool _empty(LIST_t* list)
{
    BODY_t* body = (BODY_t*)list->_body;
    return (body->_tail == NULL);
}

static int _size(LIST_t* list)
{
    BODY_t* body = (BODY_t*)list->_body;
    return body->_num;
}

static int _construct(LIST_t* list, int max_num, int max_len, void (*data_free)(void*)) // 调用前要确定 list 已经分配内存
{
    list->_body = malloc(sizeof(BODY_t));
    if(NULL == list->_body)
        return -1;
    memset(list->_body, 0, sizeof(BODY_t));
    BODY_t* body = (BODY_t*)list->_body;
    body->_max_num = max_num;
    body->_max_len = max_len;
    body->_data_free = data_free;
    
    list->push_back = _push_back;
    list->push_front = _push_front;
    list->front = _front;
    list->back = _back;
    list->pop_front = _pop_front;
    list->pop_back = _pop_back;
    list->erase = _erase;
    list->empty = _empty;
    list->size = _size;
    list->clear = _clear;
    list->destruct = _destruct;

    return 0;
}

LIST_t* create_list(int max_num, int max_len, void (*data_free)(void*))
{
    LIST_t* list =  (LIST_t*)malloc(sizeof(LIST_t));
    if(NULL == list)
        return NULL;
    memset(list, 0, sizeof(LIST_t));
    if( _construct(list, max_num, max_len, data_free)!= 0)
    {
        free(list);
        return NULL;
    }

    return list;
}

